<template>
  <a-drawer
    :width="520"
    :title="typeMap[operateType]"
    :placement="placement"
    :visible="visible"
    :maskClosable="true"
    @close="onClose"
  >
    <template #extra>
      <a-button style="margin-right: 8px" @click="onClose">
        <template #icon>
          <i class="s-icon iconfont icon-cancel" />
        </template>
        {{ t("base.cancel") }}
      </a-button>
      <a-button
        type="primary"
        :loading="addLoading"
        :disabled="drawer_disable_ok_button"
        @click="onSubmit"
      >
        <template #icon>
          <i class="s-icon iconfont icon-tubiao_tijiao" style="height: auto" />
        </template>
        {{ t("base.save") }}
      </a-button>
    </template>
    <template #default>
      <a-form
        ref="formValidate"
        :model="formInline"
        layout="vertical"
        labelAlign="right"
        autocomplete="off"
      >
        <a-form-item
          :label="t('sysMenu2')"
          :rules="[{ required: true, message: t('placeholder128') }]"
        >
          <a-radio-group
            @change="handleRadioGroup"
            v-model:value="formInline.is_menu"
          >
            <a-radio :value="0">{{ t("sysMenu19") }}</a-radio>
            <a-radio :value="1">{{ t("sysMenu20") }}</a-radio>
            <a-radio :value="2">{{ t("sysMenu21") }}</a-radio>
            <a-radio :value="3">{{ t("sysMenu22") }}</a-radio>
          </a-radio-group>
        </a-form-item>

        <a-form-item
          :label="t('sysMenu29')"
          name="name"
          :rules="[{ required: true, message: t('placeholder148') }]"
        >
          <a-input
            v-model:value="formInline.name"
            :placeholder="t('placeholder148')"
            v-input.trim.textFilter
          ></a-input>
        </a-form-item>

        <a-form-item :label="t('sysMenu4')" name="parent_id">
          <a-tree-select
            v-model:value="formInline.parent_id"
            v-input.textFilter
            showSearch
            style="width: 100%"
            :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
            :allow-clear="true"
            :tree-default-expand-all="false"
            :tree-data="tmp_treeData"
            :placeholder="t('sysMenu24')"
            :filter-tree-node="filterOption"
            @change="handleTreeChange"
            :disabled="formInline.is_menu === 0"
          >
            <template #title="{ value: val, label }">
              <i>{{ label }}</i>
            </template>
          </a-tree-select>
        </a-form-item>

        <a-form-item
          v-if="[0, 1, 3].includes(formInline.is_menu as number)"
          :label="t('sysMenu5')"
          :rules="[{ required: true, message: t('placeholder128') }]"
        >
          <a-input
            v-model:value="formInline.http_path"
            :placeholder="t('placeholder128')"
            v-input.trim.textFilter
          ></a-input>
        </a-form-item>

        <a-form-item
          v-if="[0, 1, 3].includes(formInline.is_menu as number)"
          :label="t('sysMenu6')"
          :rules="[{ required: true, message: t('placeholder129') }]"
        >
          <a-select
            v-model:value="formInline.http_method"
            :placeholder="t('placeholder129')"
            :options="httpMethodMap"
          />
        </a-form-item>

        <a-form-item
          :label="t('sysMenu7')"
          v-if="[2, 3].includes(formInline.is_menu as number)"
          :rules="[{ required: true, message: t('placeholder145') }]"
        >
          <a-input
            v-model:value="formInline.slug"
            :placeholder="t('sysMenu25')"
            v-input.trim.textFilter
          ></a-input>
        </a-form-item>

        <a-form-item
          :label="t('sysMenu8')"
          :rules="[{ required: true, message: t('placeholder146') }]"
        >
          <a-input-number
            v-model:value="formInline.sort"
            v-input.trim.textFilter.int
          />
        </a-form-item>

        <a-form-item
          v-if="[0, 1, 2].includes(formInline.is_menu as number)"
          :label="t('sysMenu9')"
          :rules="[{ required: true, message: t('placeholder147') }]"
        >
          <a-popover v-model:visible="show" placement="topLeft" trigger="click">
            <template #content>
              <div class="Grid">
                <div
                  class="grid-item"
                  v-for="(iconClass, index) in AliIcons"
                  :key="index"
                >
                  <i
                    @click="handleIcon(iconClass)"
                    :class="['iconfont', `${iconClass}`]"
                  ></i>
                </div>
              </div>
            </template>
          </a-popover>
          <a-input
            v-model:value="formInline.icon"
            @click="show = !show"
            :placeholder="t('sysMenu26')"
            v-input.trim.textFilter
            allow-clear
          >
          </a-input>
        </a-form-item>

        <a-form-item
          :label="t('sysMenu10')"
          :rules="[{ required: true, message: t('placeholder61') }]"
        >
          <a-radio-group v-model:value="formInline.visible">
            <a-radio :value="0">{{ t("sysMenu27") }}</a-radio>
            <a-radio :value="1">{{ t("sysMenu28") }}</a-radio>
          </a-radio-group>
        </a-form-item>
      </a-form>
    </template>
  </a-drawer>
</template>
<script lang="ts">
import { defineComponent, defineExpose, reactive, ref, watch } from "vue";
import { DrawerProps, message } from "ant-design-vue";
import AliIcons from "@/assets/icons/ali-icons";
import {
  formInline,
  addLoading,
  operateType,
  treeDataOptions,
  findParentNode,
} from "../../store";
import { drawer_disable_ok_button } from "../../store";
const httpMethodMap = [
  {
    label: "GET",
    value: "GET",
  },
  {
    label: "POST",
    value: "POST",
  },
  {
    label: "PUT",
    value: "PUT",
  },
  {
    label: "DELETE",
    value: "DELETE",
  },
];
export default defineComponent({
  emits: ["refreshTable"],
  setup(props, { emit }) {
    const placement = ref<DrawerProps["placement"]>("right");
    const visible = ref<boolean>(false);
    const show = ref(false);
    const typeMap: any = reactive<any>({
      edit: $t("sysMenu34"),
      add: $t("sysMenu35"),
      detail: $t("base.detail"),
    });
    const showDrawer = () => (visible.value = true);
    defineExpose({
      showDrawer,
    });
    const formValidate: any = ref(null);
    const create = async () => {
      try {
        addLoading.value = true;
        let params = lodash.omit(formInline, ["id"]);
        params.parent_id = isEmptyType(params.parent_id) ? 0 : params.parent_id;
        if (formInline.is_menu === 2)
          params = lodash.omit(formInline, ["http_method", "http_path"]);
        const res: any = await menuApi.create(params);
        if (res.code != 200) return message.error(res.message);
        const routeStore = useRouteStore();
        routeStore?.fetchMenuList();
        emit("refreshTable");
        onClose();
        message.success($t("base.addSuccess"));
      } catch (error: any) {
        message.error(error.message);
      } finally {
        addLoading.value = false;
      }
    };
    const update = async () => {
      try {
        addLoading.value = true;
        let params = lodash.omit(formInline);
        params.parent_id = isEmptyType(params.parent_id) ? 0 : params.parent_id;
        if (formInline.is_menu === 2)
          params = lodash.omit(formInline, ["http_method", "http_path"]);
        const res: any = await menuApi.update(lodash.omit(params));
        if (res.code != 200) return message.error(res.message);
        const routeStore = useRouteStore();
        routeStore?.fetchMenuList();
        emit("refreshTable");
        onClose();
        message.success($t("base.updateSucess"));
      } catch (error: any) {
        message.error(error.message);
      } finally {
        addLoading.value = false;
      }
    };
    const onSubmit = () => {
      addLoading.value = true;
      if (operateType.value === "add") create();
      if (operateType.value === "edit") update();
    };
    const onClose = () => (visible.value = false);
    const deep_treeDataOptions = (treeData: any) => {
      const data =
        treeData?.map((item: any) => {
          return {
            value: item.id,
            label: item.name,
            children: item?.children?.length
              ? deep_treeDataOptions(item.children)
              : [],
          };
        }) ?? [];
      return data;
    };
    const tmp_treeData = ref<any>([]);
    watch(
      () => treeDataOptions.value,
      () => (tmp_treeData.value = deep_treeDataOptions(treeDataOptions.value))
    );

    const handleIcon = (iconClass: any) => {
      show.value = !show.value;
      formInline.icon = iconClass;
    };
    const increaseSort = (is_menu, treeData) => {
      if (operateType.value === "add") {
        const sortMap = treeData
          .filter((item) => item.is_menu === is_menu)
          .map((item) => item.sort);
        if (!sortMap?.length) return;
        formInline.sort = Math.max(...sortMap) + 1;
      }
    };
    const handleTreeChange = (value, label, extra) => {
      const parentNode = findParentNode(treeDataOptions.value, value);
      increaseSort(formInline.is_menu, parentNode.children);
    };
    const handleRadioGroup = (e) => {
      const {
        target: { value },
      } = e;
      if (operateType.value === "add") {
        formInline.parent_id = undefined;
        if (value === 0) {
          const sortMap = treeDataOptions.value
            .filter((item) => item.is_menu === 0 && item.http_path != "/system")
            .map((item) => item.sort);
          formInline.sort = Math.max(...sortMap) + 1;
          return;
        }
        formInline.sort = 0;
      }
    };

    return {
      httpMethodMap,
      handleTreeChange,
      handleRadioGroup,
      t: $t,
      addLoading,
      formValidate,
      typeMap,
      handleIcon,
      AliIcons,
      show,
      tmp_treeData,
      onSubmit,
      formInline,
      operateType,
      placement,
      visible,
      showDrawer,
      onClose,
      drawer_disable_ok_button,
    };
  },
});
</script>

<style scoped lang="less">
.Grid {
  overflow: scroll;
  width: 340.66px;
  min-height: 22px;
  max-height: 200px;
  text-align: center;
  padding: 10px;
  box-sizing: border-box;

  .grid-item {
    border: 1px dashed #ddd;
    width: 20px;
    height: 20px;
    line-height: 20px;
    text-align: center;
    float: left;
    cursor: pointer;
  }
}
</style>
